Link to this headingMulti Party Computation Signatures
Link to this headingMPC ECDSA
Using [Shamir’s Secret Sharing](/Crypto/Key Derivation/Shamir’s Secret Sharing.md) to split a key you can use ECDSA on the shares to make partial signatures to join into the full signature.
Link to this headingImplementation
"""Modular inverse using Extended Euclidean Algorithm"""
return
"""Lagrange interpolation at x over finite field"""
= 0
=
, = ,
= 1
=
*= *
%=
+= *
%=
return
"""Generate Shamir shares of the secret"""
= +
=
=
= %
return
=
=
=
return
# Initialize curve and generator
=
=
=
# Secret key
= +1 # Ensure it's in the range [1, order-1]
= *
# Parameters for threshold scheme
= 3 # threshold
= 5 # total parties
# Create shares
=
# Message to sign
= b
= %
# Generate a random k that is the same for all parties
= + 1 # Ensure k is in the range [1, order-1]
= *
= %
=
=
=
# Each party computes its share of s
# s_i = (message_hash + random_point * share_y) % order
=
= %
# Combine shares using Lagrange interpolation to get full s
# s = k_inv * L(0, x_s, [s_i for (_, s_i) in partial_signatures]) % order
= %
= %
# ---------- Verification ----------
=
# Generated shares: [(1, mpz(3384796937180342578786757632028104081747638960432769905687896486996564190165)), (2, mpz(29174177386549707398991491821137283830538312579713319210734786325067765297975)), (3, mpz(83655921441766214215161280143676828999475799876656045425820216496384855267201)), (4, mpz(51037939865513667603725137590958831735722536572186044168339023859429672603506)), (5, mpz(47112321895108262988254049171671199892116086945378219820896371555720378801227))]
# Signature valid: True
# Signature: r = 80062998148642071209212203377843622668975090302755313217799995105627231040726, s = 2577493232225470942764247866215246781870590692477676719505009113885254605295
# Signature verification result: True
Link to this headingToy Example
#Setup Keys and message
= 13
= 2
= 5
#Share Function:f(x) = 5 + ax mod 13
#x = 1
= # f(1) = 6
= # f(2) = 7
= 2
#Setup secret Number for signature
= 3
=
= %
#Signature Parts
= %
= %
#Lagrange weights
= %
= %
#Identities
#lambda_1 + lambda_2 = 1
# This is because we are using Lagrange interpolation at x=0, which gives us
# the constant term of the polynomial, which is the sum of the weights.
#lambda_1 * share1[1] + lambda_2 * share2[1] = private_key
# hashed_message + public_int * private_key = lambda_1 * signature_1 + lambda_2 * signature_2
# ... = lambda_1 * ((hashed_message + public_int * share1[1]) % order) + lambda_2 * ((hashed_message + public_int * share2[1]) % order)
# ... = (lambda_1 * hashed_message) + (lambda_1 * public_int * share1[1]) + (lambda_2 * hashed_message) + (lambda_2 * public_int * share2[1])
# ... = hashed_message(lambda_1 + lambda_2 ) + public_int(lambda_1 * share1[1] + lambda_2 * share2[1])
# ... = hashed_message + public_int(lambda_1 * share1[1] + lambda_2 * share2[1])
# ... = hashed_message + public_int * private_key
= %
# s = k^-1 * (hashed_message + public_int * private_key)
= %
#Signature
=
# Public Int: 6, Inverse Secret Int: 9, Private Key: 5
# Signature 1: 12, Signature 2: 5
# Lagrange Weights: lambda_1 = 2, lambda_2 = 12
# Combined Signature: 2
# Signature: (6, 2)
Link to this headingSecurity
partial_signature_1 = hashed_message + public_int * share1[1]
share1[1] = (partial_signature_1 - hashed_message) / public_int
Example Attack:
"""Modular inverse using Extended Euclidean Algorithm"""
return
"""Lagrange interpolation at x over finite field"""
= 0
=
, = ,
= 1
=
*= *
%=
+= *
%=
return
"""Generate Shamir shares of the secret"""
= +
=
=
= %
return
=
=
return
# Initialize curve and generator
=
=
=
# Secret key
= + 1
= *
# Threshold settings
= 3
= 5
=
# Sign message
= b
= %
# Generate nonce
= + 1
= *
= %
=
# Select shares for signing
=
=
# Compute partial signatures
=
= %
# Interpolate to get s
= %
=
# Leak the second partial signature
, = # attacker gets this
# Use the partial signature to recover the second share
= % # recover y_i from s_i
#Leak the third share
, = # attacker gets this
# Use the partial signature to recover the third share
= % # recover y_i from s_i
# Now attacker has y1 and y2; simulate getting one more partial signature
=
=
=
# Interpolate secret
=
assert == ,
Link to this headingGG18
Link to this headingGG20
Link to this headingCGGMP21